package com.guozcc.bootweb.platform.config;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.guozcc.bootweb.platform.annotation.Trade;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import springfox.documentation.service.*;
import java.util.ArrayList;
import java.util.List;

@Configuration
//@EnableSwagger2     //开启 Swagger2
//@EnableKnife4j     //开启 knife4j，可以不写
//@EnableAutoConfiguration
//@EnableOpenApi
//@ConditionalOnProperty(prefix = "knife4j",name = "production",havingValue = "false")
public class SwaggerConfiguration {
    @Bean
    public Docket createRestfulApi(){
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("接口列表")
                .apiInfo(apiInfo())
                .pathMapping("/")
                .select()

                // 此包路径下的类，才生成接口文档
                /*
                 * RequestHandlerSelectors
                 *      .any() // 扫描全部的接口，默认
                 *      .none() // 全部不扫描
                 *      .basePackage("com.mike.server") // 扫描指定包下的接口，最为常用
                 *      .withClassAnnotation(RestController.class) // 扫描带有指定注解的类下所有接口
                 *      .withMethodAnnotation(PostMapping.class) // 扫描带有只当注解的方法接口
                 *
                 * .basePackage("com.guozcc.bootweb.api.controller")
                 */
                .apis(RequestHandlerSelectors.withMethodAnnotation(Trade.class)) //带trade注解的方法
                /*
                 * PathSelectors
                 *      .any() // 满足条件的路径，该断言总为true
                 *      .none() // 不满足条件的路径，该断言总为false（可用于生成环境屏蔽 swagger）
                 *      .ant("/user/**") // 满足字符串表达式路径
                 *      .regex("") // 符合正则的路径
                 */
                .paths(PathSelectors.any())
                .build()
                // 安全模式
                .securitySchemes(securitySchemes())
                // 安全上下文
                .securityContexts(securityContexts())
                .pathMapping("/");
    }

    /**
     * 构建 api文档的详细信息函数,注意这里的注解引用的是哪个
     * @return
     */
    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                //页面标题
                .title("API管理")
                //创建人
                .contact(new Contact("guozcc", "http://ip:port/api/", "692008977@qq.com"))
                //版本号
                .version("1.0")
                //描述
                .description("jsbank")
                .build();
    }

    /**
     * 安全模式，这里指定token通过Authorization头请求头传递
     */
    private List securitySchemes() {
        List apiKeyList = new ArrayList<>();
        apiKeyList.add(new ApiKey("authorization", "authorization", "header"));
        return apiKeyList;
    }

    /**
     * 安全上下文
     */
    private List<SecurityContext> securityContexts() {
        List<SecurityContext> securityContexts = new ArrayList<>();
        securityContexts.add(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
                        .build());
        return securityContexts;
    }

    /**
     * 默认的全局鉴权策略
     */
    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences = new ArrayList<>();
        securityReferences.add(new SecurityReference("authorization", authorizationScopes));
        return securityReferences;
    }

}
